/* Provide a read pointer function for a class member */

#ifndef MC_ACCESSOR_READ_POINTER_HPP
#define MC_ACCESSOR_READ_POINTER_HPP

#include <cassert>
#include <cstddef>
#include <stdexcept>

#include <memchart/types.hpp>
#include <memchart/type_traits.hpp>

namespace memchart
{
	template <bool IsPointer, typename C, typename T, T C::* M>
	struct accessor_read_pointer_impl
	{
		static uintptr_t read (const void * /* p */)
		{
			throw std::logic_error("read_pointer called for non-pointer type");
		}
	};

	template <typename C, typename T, T C::* M>
	struct accessor_read_pointer_impl<true, C, T, M>
	{
		static uintptr_t read (const void *p)
		{
			assert(p != NULL);

			const C & obj = *reinterpret_cast<const C *>(p);

			return reinterpret_cast<uintptr_t>(obj.*M);
		}
	};

	template <typename C, typename T, T C::* M>
	struct accessor_read_pointer :
		accessor_read_pointer_impl<is_pointer<T>::value, C, T, M>
	{ };
}

#endif /* MC_ACCESSOR_READ_POINTER_HPP */
